
#include <stdio.h>
#include <pthread.h>
#include <assert.h>
#include <limits.h>
#include <machine/machdefs.h>
#include <stdlib.h>

#include "queue.h"

#define SPIN(N_)  { int __n = (N_); while(__n--) { __sb_barrier(); }}

void
init_queue (queue_t *Q, int qsz, int bsz, char *buf)
{
  Q->head = 0;
  Q->tail = 0;
  Q->queue_size = qsz;
  Q->buf_size = bsz;
  Q->buf = buf;
}

int 	
queue_size (queue_t *Q)
{
  short head = Q->head;
  short tail = Q->tail;

  if (head >= tail) {
    return head - tail;
  }
  else {
    return head + Q->queue_size - tail;
  }
}

static void
wait_not_full (queue_t *Q)
{
  while (queue_size (Q) == Q->queue_size-1) {
    SPIN (10);
  }
}

static void
wait_not_empty (queue_t *Q)
{
  while (queue_size (Q) == 0) {
    SPIN (10);
  }
}

int check_if_queue_full(queue_t *Q)
{
    return (queue_size (Q) == Q->queue_size-1);
}

int check_if_queue_empty(queue_t *Q)
{
    return (queue_size (Q) == 0);
}

char *
enqueue_buffer (
    	queue_t		*Q
    	)
{
  return Q->buf + Q->buf_size * Q->head;
}

char *
enqueue_buffer_blocking (
    	queue_t		*Q
    	)
{
  wait_not_full (Q);
  return Q->buf + Q->buf_size * Q->head;
}

void
enqueue (
    	queue_t		*Q
    	)
{
  short	head = Q->head;
  head++;
  if (head == Q->queue_size) {
    head = 0;
  }
  Q->head = head;
}

char *
dequeue_buffer (
    	queue_t		*Q
    	)
{
  return Q->buf + Q->buf_size * Q->tail;
}

char *
dequeue_buffer_blocking (
    	queue_t		*Q
    	)
{
  wait_not_empty (Q);
  return Q->buf + Q->buf_size * Q->tail;
}

void  	
dequeue (
    	queue_t 	*Q 
    	)
{
  short tail;
  tail = Q->tail;
  tail++;
  if (tail == Q->queue_size) {
    tail = 0;
  }
  Q->tail = tail;
}

